/*  PrimeBlaster
    by Kjetil Eide 
    kjetile445@gmail.com

    This file is part of PrimeBlaster

    PrimeBlaster is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    PrimeBlaster is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with PrimeBlaster.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.eide.spaceship;

import java.lang.Math;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Image;
import org.newdawn.slick.Sound;
import org.newdawn.slick.Input;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.SlickException;

public class SpaceShip extends RigidBody {
	// space ship scaled: 120x91
	// old square ship: 120x46
	public static final float WIDTH = 120; // width 120 height 46 mass 8
	public static final float HEIGHT = 91;
	private static final float DENSITY =  0.01f; //0.00145f;   
	private static final float COEFF_OF_REST = 1f;  
	private static final float ENGINE_POWER = 10;
	private static final int ROT_ACCEL = 4; // low number = fast
	private static final float MAX_ROT_SPEED = 0.9f; // low = slow
	//private static final float MAX_SPEED_SQUARED = 1000;
	private static final float MAX_STRENGTH = 100;
	
	private float strength;	
	private boolean invincible;
	private long invincibleTimer;
	private boolean soundPlaying;
	
	
	/* indexes of the coordinates outlining the body shape */
//	public static final int[] X = new int[] {0, 2, 4, 6};
//	public static final int[] Y = new int[] {1, 3, 5, 7};
//	public static final float[] POINTS = 
//		new float[] {-WIDTH/2, -HEIGHT/2,
//					 WIDTH/2, -HEIGHT/2,
//					 WIDTH/2, HEIGHT/2,
//					 -WIDTH/2, HEIGHT/2};
//	
	public static final int[] X = new int[] {0, 2, 4, 6};
	public static final int[] Y = new int[] {1, 3, 5, 7};
	public static final float[] POINTS = 
		new float[] {-60, 0,     
					 -32, -45,   
					 60, 0,      
					 -32, 45};   
	
	private Image currentImage;
	private Sound engineLoop;
	
	/* particle system describing the engine flame */
	private EngineFlame flame; 
	
		
	/**
	 * Create new space ship object
	 * @param filename Filename of spaceship sprite
	 * @param x X-position of CM of space ship on screen cartesian coordinates
	 * @param y Y-position of CM of space ship on screen cartesian coordinates
	 * @throws SlickException
	 */
	SpaceShip(float x, float y, Image shipImage) throws SlickException {		
		super(DENSITY, WIDTH, HEIGHT, 
				COEFF_OF_REST, new Vector2f(x, y), POINTS);
		currentImage = shipImage;
		engineLoop = new Sound("spacedata/engine_loop.ogg");
		//engineLoop.loop();
		Vector2f flamePos = new Vector2f(getX(), getY());
		flame = new EngineFlame("spacedata/fire_engine.xml", flamePos);
		//flame = new EngineFlame("spacedata/JetFlame2.xml", getPos());
		strength = MAX_STRENGTH;
		invincible = false;
		soundPlaying = false;
	}
	
	public Image getImage() {
		return currentImage;
	}
	
	public EngineFlame getFlame() {
		return flame;
	}
	
	public float getStrength() {
		return strength;
	}

	public long getInvincibleTimer() {
		return invincibleTimer;
	}
	
	public boolean isInvincible() {
		return invincible;
	}

	public void setInvincible(boolean invincible) {
		this.invincible = invincible;
	}

	public void setInvincibleTimer(long invincibleTimer) {
		this.invincibleTimer = invincibleTimer;
	}	
	
	/**
	 * compute forces that will act on the ship according to controller
	 * input from the user.
	 * @param c
	 */
	public void control(GameContainer c, float timeStep) {
		float point[] = getShape().getPoints();
		
		float oldAngVelocity = getAngVelocity();
	
		float rotationIncrement = timeStep / ROT_ACCEL;
		
		if(c.getInput().isKeyDown(Input.KEY_LEFT)) {
			/* all engine are positioned on the ships vertices.
			 * all vertex-coordinates are relative to the ships CM when
			 * orientation is 0 (the ship is lying horizontally facing right
			 * vertex 0 is in 1st quadrant, vertex 1 is 2nd quadrant etc. 
			 */
			
			/* old spaceship */
//			addForce(new Vector2f(point[X[3]]-point[X[0]], point[Y[3]]-point[Y[0]]),
//					new Vector2f(point[X[3]]-getX(), point[Y[3]]-getY()));
//			
//			addForce(new Vector2f(point[X[1]]-point[X[2]], point[Y[1]]-point[Y[2]]),
//					new Vector2f(point[X[1]]-getX(), point[Y[1]]-getY()));

			/*spaceship_scaled */
//			addForce(new Vector2f(point[X[0]]-point[X[1]], point[Y[0]]-point[Y[1]]).scale(4),
//					new Vector2f(point[X[1]]-getX(), point[Y[1]]-getY()));			
//			addForce(new Vector2f(point[X[2]]-point[X[3]], point[Y[2]]-point[Y[3]]).scale(2),
//					new Vector2f(point[X[3]]-getX(), point[Y[3]]-getY()));			
			addAngVelocity(-rotationIncrement);
			
		
		}
		if(c.getInput().isKeyDown(Input.KEY_RIGHT)) {
//			addForce(new Vector2f(point[X[0]]-point[X[3]], point[Y[0]]-point[Y[3]]),
//					new Vector2f(point[X[3]]-getX(), point[Y[3]]-getY()));
//			
//			addForce(new Vector2f(point[X[2]]-point[X[1]], point[Y[2]]-point[Y[1]]),
//					new Vector2f(point[X[1]]-getX(), point[Y[1]]-getY()));
		
			
			/*spaceship scaled */
//			addForce(new Vector2f(point[X[1]]-point[X[0]], point[Y[1]]-point[Y[0]]).scale(4),
//					new Vector2f(point[X[1]]-getX(), point[Y[1]]-getY()));
//			addForce(new Vector2f(point[X[3]]-point[X[2]], point[Y[3]]-point[Y[2]]).scale(4),
//					new Vector2f(point[X[3]]-getX(), point[Y[3]]-getY()));
			addAngVelocity(rotationIncrement);
			
		}
		if(c.getInput().isKeyDown(Input.KEY_UP)) {
//			addForce(new Vector2f(point[X[1]]-point[X[0]], point[Y[1]]-point[Y[0]]),
//					new Vector2f(point[X[0]]-getX(), point[Y[0]]-getY()));
//			
//			addForce(new Vector2f(point[X[2]]-point[X[3]], point[Y[2]]-point[Y[3]]),
//					new Vector2f(point[X[3]]-getX(), point[Y[3]]-getY()));
			
			
			/*spaceship sclaed */
		//	if (getVelocity().lengthSquared() < MAX_SPEED_SQUARED) {
				addForce(new Vector2f(getX()-point[X[0]], getY()-point[Y[0]]).scale(ENGINE_POWER),
					new Vector2f(point[X[0]]-getX(), point[Y[0]]-getY()));
			//}
			flame.setEnginesOn();
			setEngineSound(true);
		} else {
			flame.setEnginesOff();
			setEngineSound(false);
		}
				
		if (Math.abs(getAngVelocity()) > MAX_ROT_SPEED) {
			setAngVelocity(oldAngVelocity);
		}			
	}
	
	public void configureEngineFlames(int delta) {
		/* Calculate the position of the engine flame */ 
		
		Vector2f engPos = 
			new Vector2f(getShape().getPoints()[X[0]],
						getShape().getPoints()[Y[0]]);
		
		flame.setPos(engPos);
		flame.setOrientation((int)getOrientation('D'));
		flame.update(delta);
	}
	
	public void reset(float x, float y) {
		setPos(x, y);
		setVelocity(new Vector2f(0,0));
		setAngVelocity(0);
		setOrientation(0);
		strength = MAX_STRENGTH;
	}
	
	public boolean isUnmovable() {
		return false;
	}
	
	public void reduceStrength(float amount) {
		strength -= amount;
	}
	
	private void setEngineSound(boolean on) {
		if (on) {
			if (!soundPlaying) {
				// slick .isPlaying() i buggy. returns true if
				// ANY sound is playing. 
				engineLoop.loop();
				soundPlaying = true;
			}
		} else {
			if (soundPlaying) {
				engineLoop.stop();
				soundPlaying = false;
				//System.out.println("stoppet motorlyd");
			}
		}
	}
	
}
